import CryptoJS from 'crypto-js';
type HxCryptoOpts = {
  key: string;
  iv: string;
};

/*
  基本参数

  模式mode：         CBC
  填充padding：      0
  数据块blockSize：  128
  key：             2858310341595137
  iv：              2890256383840258
  输出：             base64
 */
const cipherParams = {
  mode: CryptoJS.mode.CBC,
  padding: CryptoJS.pad.ZeroPadding,
  blockSize: 128,
};
export default class HxCrypto {
  static instance: HxCrypto;

  /**
   * @param opts
   * @brief 使用前必须初始化
   */
  static init(opts: HxCryptoOpts) {
    if (!this.instance) {
      this.instance = new HxCrypto(opts);
    }
    return this.instance;
  }

  /**
   * @param text 待加密文本
   * @brief 加密文本
   */
  static encrypt(text: string) {
    return this.instance.encrypt(text);
  }

  /**
   * @param cryptText 待解密的文本
   * @brief 解密文本
   */
  static decrypt(cryptText: string) {
    return this.instance.decrypt(cryptText);
  }

  private _encryptKey = CryptoJS.enc.Utf8.parse('');
  private _encryptIv = CryptoJS.enc.Utf8.parse('');

  constructor(opts: HxCryptoOpts) {
    this._encryptKey = CryptoJS.enc.Utf8.parse(opts.key);
    this._encryptIv = CryptoJS.enc.Utf8.parse(opts.iv);
  }

  /**
   * @param text 待加密内容
   * @brief 加密文本
   */
  encrypt(text: string) {
    const encryptedData = CryptoJS.AES.encrypt(text, this._encryptKey, {
      iv: this._encryptIv,
      ...cipherParams,
    });
    return CryptoJS.enc.Base64.stringify(encryptedData.ciphertext);
  }

  decrypt(cryptText: string) {
    const encryptedHexStr = CryptoJS.enc.Base64.parse(cryptText);
    const encryptedBase64Str = CryptoJS.enc.Base64.stringify(encryptedHexStr);
    const decryptedData = CryptoJS.AES.decrypt(encryptedBase64Str, this._encryptKey, {
      iv: this._encryptIv,
      ...cipherParams,
    });
    return decryptedData.toString(CryptoJS.enc.Utf8);
  }
}
